package endpoint

import (
	"context"
	"fmt"
	"github.com/go-kit/kit/endpoint"
	"github.com/go-kit/kit/metrics"
	pb "mytest/gokit/proto/hello"
	"time"
)

// WrapEndpoints accepts the service's entire collection of endpoints, so that a
// set of middlewares can be wrapped around every middleware (e.g., access
// logging and instrumentation), and others wrapped selectively around some
// endpoints and not others (e.g., endpoints requiring authenticated access).
// Note that the final middleware wrapped will be the outermost middleware
// (i.e. applied first)
func WrapEndpoints(in Endpoints) Endpoints {

	// Pass a middleware you want applied to every endpoint.
	// optionally pass in endpoints by name that you want to be excluded
	// e.g.
	// in.WrapAllExcept(authMiddleware, "Status", "Ping")
	in.WrapAllExcept(LoggingMiddleware)

	// Pass in a svc.LabeledMiddleware you want applied to every endpoint.
	// These middlewares get passed the endpoints name as their first argument when applied.
	// This can be used to write generic metric gathering middlewares that can
	// report the endpoint name for free.
	// github.com/metaverse/truss/_example/middlewares/labeledmiddlewares.go for examples.
	//in.WrapAllLabeledExcept(Latency(dur))

	//注入全局中间件
	in.WrapAllLabeledExcept(AuthMiddleware())

	// How to apply a middleware to a single endpoint.
	// in.ExampleEndpoint = authMiddleware(in.ExampleEndpoint)

	//注入单个请求中间件
	//in.SayHelloEndpoint = LoggingMiddleware(in.SayHelloEndpoint)
	return in
}

func WrapService(in pb.HelloServer) pb.HelloServer {
	return in
}

// ErrorCounter is a LabeledMiddleware, when applied with WrapAllLabeledExcept name will be populated with the endpoint name, and such this middleware will
// report errors to the metric provider with the endpoint name. Feel free to
// copy this example middleware to your service.
func ErrorCounter(errCount metrics.Counter) LabeledMiddleware {
	return func(name string, in endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, req interface{}) (interface{}, error) {
			resp, err := in(ctx, req)
			if err != nil {
				errCount.With("endpoint", name).Add(1)
			}
			return resp, err
		}
	}
}

// Latency is a LabeledMiddleware, reporting the request time of and
// endpoint along with its name
func Latency(h metrics.Histogram) LabeledMiddleware {
	return func(name string, in endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, req interface{}) (interface{}, error) {
			defer func(begin time.Time) {
				h.With("endpoint", name).Observe(time.Since(begin).Seconds())
			}(time.Now())
			return in(ctx, req)
		}
	}
}

//单个中间件
func LoggingMiddleware(next endpoint.Endpoint) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		fmt.Printf("this is login middleware \n")
		return next(ctx, request)
	}
}

//全局中间件
func AuthMiddleware() LabeledMiddleware {
	return func(name string, in endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, req interface{}) (interface{}, error) {
			fmt.Printf("this is auth middleware \n")
			fmt.Printf("centerid : %s \n", ctx.Value("centerid"))
			fmt.Printf("source : %s \n", ctx.Value("source"))
			fmt.Printf("uuid : %s \n", ctx.Value("uuid"))
			fmt.Printf("method : %s \n", ctx.Value("method"))
			fmt.Printf("method : %s \n", ctx.Value("hshshshsh"))
			return in(ctx, req)

		}
	}
}
